package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.Sign;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.rooms.absrooms.AbsDiffViewChessRoom;
import com.myk.game.gobangchess.rooms.absrooms.movechess.MoreColorCost;
import com.myk.game.gobangchess.signs.*;
import com.myk.game.gobangchess.utils.GridsUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 跳步国际象棋
 * sng又一个尝试
 */
public class JumpStepForeignChessRoom extends AbsDiffViewChessRoom {

    private CacheSign chessBoardCacheSign; //背景缓存标记
    private CacheSign detentionPlatCacheSign; //拘台缓存标记

    private final List<int[]> moveArrayList = new ArrayList<>(); // 棋子移动标记
    private Integer putPoint = null; //打入落子标记
    private List<Chess> chessList; //场上棋子集合

    private Sider blackSider; //游戏黑方实体
    private Sider whiteSider; //游戏白方实体

    public JumpStepForeignChessRoom(String roomName) {
        super(roomName, "将跳棋元素引入国际象棋，棋子可向前跳跃一到两步远。去掉了国际象棋的特殊走法与逼和规则。并且王也可以升变。", "跳步国际象棋", GridsUtils.createEmptyGrids(8, 8), true, true);
        initChessBoardCacheSign();
        initDetentionPlatCacheSign();
    }

    //棋盘背景的设计
    private void initChessBoardCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        int row = curGrids.length;
        int col = curGrids[0].length;
        //绘制类似国际象棋的黑白相间的格子
        List<Integer> bGrids = new ArrayList<>();
        List<Integer> wGrids = new ArrayList<>();
        for (int i = 0; i < row; i++) {
            for (int j = 0; j < col; j++) {
                int index = getIndex(i, j);
                if ((i + j) % 2 == 0) {
                    wGrids.add(index);
                }
                else {
                    bGrids.add(index);
                }
            }
        }
        chessboardStyle.add(new ColorSign(bGrids, "#FF888888"));
        chessboardStyle.add(new ColorSign(wGrids, "#FFDDDDDD"));
        //画边框
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(row-1, col-1), "#00000000", "#FFAA6622", 2.2f, 0, 0));
        //将背景封装为缓存标记
        chessBoardCacheSign = new CacheSign(this,"background",5,true,chessboardStyle); //*** 修改背景样式记得改这里的版本号！！！
    }

    //拘台背景的设计
    private void initDetentionPlatCacheSign() {
        List<Sign> chessboardStyle = new ArrayList<>();
        //背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), MoreColorCost.BOARD_BACKGROUND, MoreColorCost.BOARD_BACKGROUND, 1.8f, 0, 0));
        //虚化背景
        chessboardStyle.add(new GroundSign(getIndex(0, 0), getIndex(curGrids.length - 1, curGrids[0].length - 1), "#99BEB2B3", "#99BEB2B3", 1.8f, 0, 0));
        //添加到缓存标记
        detentionPlatCacheSign = new CacheSign(this, "detentionPlatCacheSign", 1, true, chessboardStyle);//*** 修改背景样式记得改这里的版本号！！！
    }

    //初始化棋子列表
    private void initChessList() {
        chessList = new ArrayList<>();
        //--摆放规则：无论是白方视野还是黑方视野，棋盘的最右下角的一格一定要是白色，白后一定要放在白格上，黑后一定要放在黑格上，白王一定在 e1 格，黑王一定在 e8 格。
        //黑方在上半区
        chessList.add(new Rook(this, "车",1, 0, 0));
        chessList.add(new Knight(this, "马",1, 0, 1));
        chessList.add(new Bishop(this, "象",1, 0, 2));
        chessList.add(new Queen(this, "后",1, 0, 3));
        chessList.add(new King(this, "王",1, 0, 4));
        chessList.add(new Bishop(this, "象",1, 0, 5));
        chessList.add(new Knight(this, "马",1, 0, 6));
        chessList.add(new Rook(this, "车",1, 0, 7));
        chessList.add(new Pawn(this, "兵",1, 1, 0));
        chessList.add(new Pawn(this, "兵",1, 1, 1));
        chessList.add(new Pawn(this, "兵",1, 1, 2));
        chessList.add(new Pawn(this, "兵",1, 1, 3));
        chessList.add(new Pawn(this, "兵",1, 1, 4));
        chessList.add(new Pawn(this, "兵",1, 1, 5));
        chessList.add(new Pawn(this, "兵",1, 1, 6));
        chessList.add(new Pawn(this, "兵",1, 1, 7));
        //白方在下半区
        chessList.add(new Pawn(this, "兵",2, 6, 0));
        chessList.add(new Pawn(this, "兵",2, 6, 1));
        chessList.add(new Pawn(this, "兵",2, 6, 2));
        chessList.add(new Pawn(this, "兵",2, 6, 3));
        chessList.add(new Pawn(this, "兵",2, 6, 4));
        chessList.add(new Pawn(this, "兵",2, 6, 5));
        chessList.add(new Pawn(this, "兵",2, 6, 6));
        chessList.add(new Pawn(this, "兵",2, 6, 7));
        chessList.add(new Rook(this, "车",2, 7, 0));
        chessList.add(new Knight(this, "马",2, 7, 1));
        chessList.add(new Bishop(this, "象",2, 7, 2));
        chessList.add(new Queen(this, "后",2, 7, 3));
        chessList.add(new King(this, "王",2, 7, 4));
        chessList.add(new Bishop(this, "象",2, 7, 5));
        chessList.add(new Knight(this, "马",2, 7, 6));
        chessList.add(new Rook(this, "车",2, 7, 7));
    }

    //检测胜负
    public void checkOver() {
        stepAdd();
        //胜负判断有点复杂，暂时只判断是否吃掉对方的帅
        if (hasChessType(blackSider.captiveList, King.class)) {
            doOver(WinMode.BLACK_WIN, "黑方获胜！");
            return;
        }
        else if (hasChessType(whiteSider.captiveList, King.class)) {
            doOver(WinMode.WHITE_WIN, "白方获胜！");
            return;
        }
        //++还要判断是否无棋可走
        //++还要判断是否长将循环
        changeNoticeMove();//切换行动方
    }

    //切换行动方
    public void changeNoticeMove() {
        if (cur == 1) {
            noticeWhiteMove();
        }
        else {
            noticeBlackMove();
        }
    }

    //根据坐标搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByPos(int row, int col) {
        for (Chess chess : chessList) {
            if (chess.row == row && chess.col == col) {
                return chess;
            }
        }
        return null;
    }

    //根据index搜索棋子 （有多个棋子时取城门之上的棋子, 可为空）
    public Chess getChessByIndex(int index) {
        for (Chess chess : chessList) {
            if (chess.getIndex() == index) {
                return chess;
            }
        }
        return null;
    }

    //检测棋子集合中是否包含某个类型的棋子
    public boolean hasChessType(List<Chess> list, Class<? extends Chess> chessType) {
        for (Chess chess : list) {
            if (chess.getClass() == chessType) {
                return true;
            }
        }
        return false;
    }

    //检测坐标位置是否在棋盘内
    public boolean isInGrids(int row, int col) {
        return row >= 0 && row < curGrids.length && col >= 0 && col < curGrids[0].length;
    }

    @Override
    public CacheSign getCacheSignByName(String cacheName) {
        if (cacheName.equals("detentionPlatCacheSign")) {
            return detentionPlatCacheSign;
        }
        else if (cacheName.equals("chessBoardCacheSign")) {
            return chessBoardCacheSign;
        }
        return chessBoardCacheSign;
    }

    @Override
    public String getRuleText() {
        return "《跳步国际象棋》\n" +
                "以国际象棋为基础，增加如下规则。\n" +
                "本方棋子A可越过相邻的或相隔一个空格正前方或斜前方的本方棋子B跳到B的正前方或斜前方的相邻空格。\n" +
                "本方棋子A处在棋盘四角时，还可以横向越过相邻的或相隔一个空格的本方棋子B调到B的左侧或者右侧。" +
                "兵只能向前走一格，兵到达对方底线立即升变成后。\n" +
                "没有王车易位。\n" +
                "王走到对方底线升变为皇帝，增加马的走法吃法。";
    }

    @Override
    public String getCoordMode() {
        return "41410000";
    }

    @Override
    public int getCountdownSec() {
        return 180; //传入象棋思考时间比较长，改成300s吧
    }

    @Override
    public String getGameInfo(int viewPoint) {
        //先清空棋盘
        signList.clear();
        //三种身份各自视角的自定义绘制
        if (viewPoint == 1) {
            blackSider.render();
        }
        else if (viewPoint == 2) {
            whiteSider.render();
        }
        else {
            publicRender();
        }
        return super.getGameInfo();
    }

    //公共渲染
    public void publicRender() {
        //画棋盘背景
        signList.add(chessBoardCacheSign);
        //绘制场上棋子
        renderChessList();
        //绘制移动箭头
        renderMoveArray();
        //绘制打入落子标记
        renderPutPoint();
    }

    //遍历绘制场上棋子
    public void renderChessList() {
        curGrids = GridsUtils.copyGrids(originGrids);
        if (chessList != null) {
            for (Chess piece : chessList) {
                curGrids[piece.row][piece.col] = piece.side; //显示棋子的底座
                signList.add(new TextSign(getIndex(piece.row, piece.col), piece.getName(), piece.side == 1 ? ColorCost.WHITE : ColorCost.BLACK)); //绘制棋子外观
            }
        }
    }

    //绘制移动箭头
    public void renderMoveArray() {
        for (int[] moveArray : moveArrayList) {
            signList.add(new LineSign(moveArray[0], moveArray[1], ColorCost.MOVE_ARROW_LIGHT, 1));
        }
    }

    //绘制打入落子标记
    private void renderPutPoint() {
        if (putPoint != null){
            signList.add(new GroundSign(putPoint, "#00000000", ColorCost.NEW_PUT_POINT, 1.0f, 0, 0));
        }
    }

    @Override
    protected void onStartPrepare() {
        //初始化场上棋子
        initChessList();
        //初始化对弈双方状态
        blackSider = new Sider(this, 1);
        whiteSider = new Sider(this, 2);
        noticeWhiteMove(); //默认通知黑方先行动
    }

    @Override
    protected void prepareInGameButtons() {
        //++暂时放弃持拘功能

//        //绑定切换拘台按钮
//        if (player_black != player_white) {
//            player_black.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> blackSider.switchPlat()));
//            player_white.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> whiteSider.switchPlat()));
//        }
//        else {
//            player_black.registerCustomBottom(new CustomBottom(this, "切换拘台", p -> {
//                if (cur == 1) blackSider.switchPlat();
//                else if (cur == 2) whiteSider.switchPlat();
//            }));
//        }
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        moveArrayList.clear();
        putPoint = null;
        chessList = null;
        blackSider = null;
        whiteSider = null;
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (value == 1) {
            blackSider.doRule(row, col);
        }
        else if (value == 2) {
            whiteSider.doRule(row, col);
        }
    }

    /**
     * 对弈双方的各种信息
     */
    private static class Sider {

        public JumpStepForeignChessRoom room;
        private final int side;//归属黑棋还是白棋 1黑  2白
        private boolean isOpenPlat; //是否展开了拘台显示
        private final List<Chess> captiveList; //俘虏棋子集合
        private Chess choose; //当前选中的场上棋子
        private Chess captive; //当前选中的持拘棋子

        public Sider(JumpStepForeignChessRoom room, int side) {
            this.room = room;
            this.side = side;
            this.captiveList = new ArrayList<>();
        }

        //私有独立界面渲染
        public void render() {
            //拘台打开状态显示拘台
            if (isOpenPlat) {
                //画拘台相关私有画面
                renderDetentionPlat();
            }
            //拘台关闭状态显示棋盘
            else {
                //画棋盘背景、场上棋子、俘虏预览、移动路径等公共画面
                room.publicRender();
                //场上棋子选中效果等私有画面
                if (choose != null) {
                    renderChessChoose();
                }
                else if (captive != null){
                    renderCaptiveChoose();
                }
            }
        }

        //拘台的绘制
        private void renderDetentionPlat() {
            //画拘台遮罩背景
            room.signList.add(room.detentionPlatCacheSign);
            //遍历绘制拘台棋子
            room.curGrids = GridsUtils.copyGrids(room.originGrids);
            for (int i = 0; i < captiveList.size(); i++) {
                Chess chess = captiveList.get(i);
                //棋子绘制的位置根据在captiveList中的位置来
                int cR = room.curGrids.length - 2 - (i / 7);
                int cC = i % 7 + 1;
                room.curGrids[cR][cC] = chess.isCompleteCaptive?chess.side:7; //显示棋子的底座
                chess.row = cR; //正常不该在这里修改棋子状态的，但是可以解决选中俘虏时根据坐标逆运算棋子索引的代码，并且我确保这里不会导致其它bug
                chess.col = cC;
                String textColor = chess.side == 1 ? ColorCost.WHITE : ColorCost.BLACK;
                room.signList.add(new TextSign(room.getIndex(cR, cC), chess.getName(), textColor)); //绘制棋子外观
                //画拘台持拘棋子选中效果
                if (captive != null && captive == chess) {
                    room.signList.add(new GroundSign(room.getIndex(cR, cC), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
                }
            }
        }

        //当前选中棋子的绘制
        private void renderChessChoose() {
            //画选中绿框
            room.signList.add(new GroundSign(choose.getIndex(), "#00FFFFFF", "#FF33CC33", 2F, 0, 1));
            //画一下可移动范围
            for (Integer index : choose.getMoveRange()) {
                room.signList.add(new ColorSign(index, MoreColorCost.MOVE));
            }
            //画一下吃子范围
            for (Integer index : choose.getEatRange()) {
                room.signList.add(new ColorSign(index, MoreColorCost.EAT));
            }
        }

        //当前选中俘虏棋子的绘制
        private void renderCaptiveChoose() {
            for (Integer index : captive.getPutRange()) {
                room.signList.add(new ColorSign(index, MoreColorCost.MOVE));
            }
        }

        //切换拘台显示
        public void switchPlat() {
            this.isOpenPlat = !isOpenPlat;
            room.noticeAllRefreshGameInfo();
        }

        //私有独立交互逻辑处理
        public void doRule(int row, int col) {
            //在拘台上点击
            if (isOpenPlat) {
                Chess chess = getByCaptiveList(row, col);
                if (chess != null) chooseCaptive(chess);
            }
            //在棋盘上点击
            else {
                //已选中场上棋子时
                if (choose != null) {
                    Chess newChess = room.getChessByPos(row, col);
                    //再点击空格
                    if (newChess == null) {
                        if (choose.getMoveRange().contains(room.getIndex(row, col))) {
                            moveChess(row, col); //移动选中棋子
                        }
                        else {
                            cancelChoose(); //取消选中棋子
                        }
                    }
                    //再点击己方棋子时
                    else if (newChess.side == side) {
                        chooseChess(newChess); //另选其它己方棋子
                    }
                    //再点击对方棋子时
                    else {
                        if (choose.getEatRange().contains(newChess.getIndex())) {
                            eatChess(newChess); //吃掉对方棋子
                        }
                        else {
                            cancelChoose(); //取消选中棋子
                        }
                    }
                }
                //已选中俘虏时
                else if (captive != null) {
                    //再点击己方棋子都可以当作打入底座
                    if (captive.getPutRange().contains(room.getIndex(row, col))) {
                        putChess(row, col); //打入棋子
                    }
                    //再点击对方棋子或者空格
                    else {
                        cancelCaptive();
                    }
                }
                //未选中任何棋子时
                else {
                    Chess chess = room.getChessByPos(row, col);
                    if (chess != null && chess.side == side) {
                        chooseChess(chess);
                    }
                }
            }
        }

        //添加棋子到拘台
        private void addCaptiveInPlat(Chess target) {
            for (Chess chess : captiveList) {
                if (chess.getClass() == target.getClass()){
                    if (!chess.isCompleteCaptive) {
                        chess.isCompleteCaptive = true;  //遇到相同的棋子，两个虚的合成一个实的可以打入的
                        return;
                    }
                }
            }
            captiveList.add(target);
        }

        //获取当前位置的俘虏棋子
        public Chess getByCaptiveList(int row, int col) {
            for (Chess chess : captiveList) {
                if (chess.isCompleteCaptive && chess.getIndex() == room.getIndex(row, col)) {
                    return chess;
                }
            }
            return null;
        }

        //选中棋子
        private void chooseChess(Chess choose) {
            this.captive = null;
            this.choose = choose;
            room.noticeAllRefreshGameInfo();
        }

        //选中俘虏
        private void chooseCaptive(Chess captive) {
            this.choose = null;
            this.captive = captive;
            switchPlat();
        }

        //取消场上棋子的选中
        private void cancelChoose() {
            this.choose = null;
            room.noticeAllRefreshGameInfo();
        }

        //取消俘虏的选中
        private void cancelCaptive() {
            this.captive = null;
            room.noticeAllRefreshGameInfo();
        }

        //移动棋子
        private void moveChess(int row, int col) {
            //更新移动标记
            room.moveArrayList.clear();
            room.moveArrayList.add(new int[]{choose.getIndex(), room.getIndex(row, col)});
            room.putPoint = null;
            //更新棋子坐标
            choose.row = row;
            choose.col = col;
            //检查兵的升变
            if (choose instanceof Pawn){
                room.chessList.remove(choose);
                room.chessList.add(((Pawn) choose).evolution());
            }
            //检查王的升变
            if (choose instanceof King){
                ((King) choose).evolution();
            }
            //移动过后选中状态取消
            choose = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

        //吃掉棋子
        private void eatChess(Chess target) {
            //更新移动标记
            room.moveArrayList.clear();
            room.moveArrayList.add(new int[]{choose.getIndex(), target.getIndex()});
            room.putPoint = null;
            //被吃棋子移到拘台
            room.chessList.remove(target);
            this.addCaptiveInPlat(target);
            //更新棋子坐标
            choose.row = target.row;
            choose.col = target.col;
            //检查兵的升变
            if (choose instanceof Pawn){
                room.chessList.remove(choose);
                room.chessList.add(((Pawn) choose).evolution());
            }
            //检查王的升变
            if (choose instanceof King){
                ((King) choose).evolution();
            }
            //移动过后选中状态取消
            choose = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

        //打入棋子
        private void putChess(int row, int col) {
            //更新记录打入标记
            room.moveArrayList.clear();
            room.putPoint = room.getIndex(row,col);
            //拘台棋子放到棋盘
            captiveList.remove(captive);
            captive.side = side; //打入棋子变成己方的
            captive.row = row;
            captive.col = col;
            captive.isCompleteCaptive = false; //再将这个标记变为false以免下次被对方再吃回去直接就是实的
            if (captive instanceof Pawn){
                captive = ((Pawn)captive).evolution(); //检查老兵升变
            }
            if (choose instanceof King){
                ((King) choose).evolution(); //检查王的升变
            }
            room.chessList.add(captive); //被打入棋子添加到场上
            //打入过后取消选中状态
            captive = null;
            //检查回合是否结束（切换行动方）
            room.checkOver();
        }

    }

    /**
     * 棋子公共抽象类
     */
    private abstract static class Chess {

        public JumpStepForeignChessRoom room;
        public String name;
        public int side;
        public int row;
        public int col;
        public boolean isCompleteCaptive; //作为俘虏时是否完整

        public Chess(JumpStepForeignChessRoom room, String name, int side, int row, int col) {
            this.room = room;
            this.name = name;
            this.side = side;
            this.row = row;
            this.col = col;
        }

        //获取棋子名称
        public String getName() {
            return name;
        }

        //判断自己是否在敌方底线
        protected boolean inEnemyBottomLine() {
            if (side == 1){
                return row == room.curGrids.length-1;
            }
            else {
                return row == 0;
            }
        }

        //获取棋子的坐标索引
        public int getIndex() {
            return room.getIndex(row, col);
        }

        //获取前方
        protected int getFrontDirection() {
            if (side == 1) {
                return 1;
            }
            else if (side == 2) {
                return -1;
            }
            else {
                return 0;
            }
        }

        //获取自身一周周围的格子（自身为中心“田”区，棋盘范围之外的不加入，最多8个格子）
        protected List<Integer> getAroundRange() {
            int[][] dxdys = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int x = row + dxdy[0];
                int y = col + dxdy[1];
                if (x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && room.curGrids[x][y] == 0) {
                    rangeIndex.add(room.getIndex(x, y));
                }
            }
            return rangeIndex;
        }

        //获取自身前方和斜前方的空格
        protected List<Integer> getFrontAroundRange() {
            int[][] dxdys = {{getFrontDirection(), -1}, {getFrontDirection(), 0}, {getFrontDirection(), 1}};
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int x = row + dxdy[0];
                int y = col + dxdy[1];
                if (x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && room.curGrids[x][y] == 0) {
                    if (room.getChessByPos(x, y) == null){
                        rangeIndex.add(room.getIndex(x, y));
                    }
                }
            }
            return rangeIndex;
        }

        //获取跳步的范围
        protected List<Integer> getJumpStepRange() {
            List<Integer> rangeIndex = new ArrayList<>();
            Chess leftFrontChess = room.getChessByPos(row + getFrontDirection(), col - 1);
            if (leftFrontChess != null && leftFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(),col - 2) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(),col - 2) == null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(),col - 2));
            }
            Chess leftFront2Chess = room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col - 2);
            if (leftFrontChess == null && leftFront2Chess != null && leftFront2Chess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection()+ getFrontDirection(),col - 3) && room.getChessByPos(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col - 3) == null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col - 3));
            }
            Chess rightFrontChess = room.getChessByPos(row + getFrontDirection(), col + 1);
            if (rightFrontChess != null && rightFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(),col + 2) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(),col + 2) == null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(),col + 2));
            }
            Chess rightFront2Chess = room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col + 2);
            if (rightFrontChess == null && rightFront2Chess != null && rightFront2Chess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection()+ getFrontDirection(),col + 3) && room.getChessByPos(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col + 3) ==  null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col + 3));
            }
            Chess upFrontChess = room.getChessByPos(row + getFrontDirection(), col);
            if (upFrontChess != null && upFrontChess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection(),col) && room.getChessByPos(row + getFrontDirection() + getFrontDirection(),col) == null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection(),col));
            }
            Chess upFront2Chess = room.getChessByPos(row + getFrontDirection() + getFrontDirection(), col);
            if (upFrontChess == null && upFront2Chess != null && upFront2Chess.side == this.side && room.isInGrids(row + getFrontDirection() + getFrontDirection()+ getFrontDirection(),col) && room.getChessByPos(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col) == null){
                rangeIndex.add(room.getIndex(row + getFrontDirection() + getFrontDirection() + getFrontDirection(),col));
            }
            if (row == 0 && col == 0){
                Chess rightChess = room.getChessByPos(0, 1);
                if (rightChess != null && rightChess.side == this.side && room.getChessByPos(0,2) == null){
                    rangeIndex.add(room.getIndex(0,2));
                }
                Chess right2Chess = room.getChessByPos(0, 2);
                if (rightChess == null && right2Chess != null && right2Chess.side == this.side && room.getChessByPos(0,3) == null){
                    rangeIndex.add(room.getIndex(0,3));
                }
            }
            if (row == 0 && col == room.curGrids[0].length - 1){
                Chess leftChess = room.getChessByPos(0, col - 1);
                if (leftChess != null && leftChess.side == this.side && room.getChessByPos(0,col - 2) == null){
                    rangeIndex.add(room.getIndex(0,col - 2));
                }
                Chess left2Chess = room.getChessByPos(0, col - 2);
                if (leftChess == null && left2Chess != null && left2Chess.side == this.side && room.getChessByPos(0,col - 3) == null){
                    rangeIndex.add(room.getIndex(0,col - 3));
                }
            }
            if (row == room.curGrids.length - 1 && col == 0){
                Chess rightChess = room.getChessByPos(row, 1);
                if (rightChess != null && rightChess.side == this.side && room.getChessByPos(row,2) == null){
                    rangeIndex.add(room.getIndex(row,2));
                }
                Chess right2Chess = room.getChessByPos(row, 2);
                if (rightChess == null && right2Chess != null && right2Chess.side == this.side && room.getChessByPos(row,3) == null){
                    rangeIndex.add(room.getIndex(row,3));
                }
            }
            if (row == room.curGrids.length - 1 && col == room.curGrids[0].length - 1){
                Chess leftChess = room.getChessByPos(row, col - 1);
                if (leftChess != null && leftChess.side == this.side && room.getChessByPos(row,col - 2) == null){
                    rangeIndex.add(room.getIndex(row,col - 2));
                }
                Chess left2Chess = room.getChessByPos(row, col - 2);
                if (leftChess == null && left2Chess != null && left2Chess.side == this.side && room.getChessByPos(row,col - 3) == null){
                    rangeIndex.add(room.getIndex(row,col - 3));
                }
            }
            return rangeIndex;
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance) {
            return defMoveRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的移动范围
        protected List<Integer> defMoveRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) { //否则遇到棋子阻碍就得停下
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                        continue;
                    }
                    if (skip >= mustJump) {
                        rangeIndex.add(room.getIndex(x, y));
                    }
                }
            }
            rangeIndex.addAll(getJumpStepRange()); //增加跳步走法
            return rangeIndex;
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance) {
            return defEatRange(dxdys, distance, 0, 0);
        }

        //根据规则搜索棋子默认的吃子范围
        protected List<Integer> defEatRange(int[][] dxdys, int distance, int canJump, int mustJump) {
            List<Integer> rangeIndex = new ArrayList<>();
            for (int[] dxdy : dxdys) {
                int skip = 0;
                for (int x = row + dxdy[0], y = col + dxdy[1], i = 0; x >= 0 && x < room.curGrids.length && y >= 0 && y < room.curGrids[0].length && i < distance; x += dxdy[0], y += dxdy[1], i++) {
                    Chess chess = room.getChessByPos(x, y);
                    if (chess != null) {
                        if (chess.side != this.side && skip >= mustJump) {
                            rangeIndex.add(room.getIndex(x, y));
                        }
                        skip++;
                        if (skip > canJump) {
                            break;
                        }
                    }
                }
            }
            return rangeIndex;
        }

        /**
         * 自定义 获取可移动空格范围
         */
        public abstract List<Integer> getMoveRange();

        /**
         * 自定义 获取可吃棋子范围
         */
        public abstract List<Integer> getEatRange();

        /**
         * 自定义 获取可打入落点空格范围
         */
        public List<Integer> getPutRange(){
            Set<Integer> range = new HashSet<>();
            for (Chess chess : room.chessList) {
                if (chess.side != this.side){
                    range.addAll(chess.getFrontAroundRange());
                }
            }
            return new ArrayList<>(range);
        }

    }

    /**
     * 国王
     */
    private static class King extends Chess {

        private boolean isCoronation = false; //是否升变为皇帝

        public King(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        /**
         * 国王升变检查
         */
        public void evolution() {
            if (inEnemyBottomLine()){
                isCoronation = true; //一旦进入对方底线就立即升变为皇帝
            }
        }

        @Override
        public String getName() {
            if (isCoronation && this.side == 1){
                return "帝";
            }
            if (isCoronation && this.side == 2){
                return "皇";
            }
            return "王";
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},{-1,-1},{1,-1},{-1,1},{1,1}}, 1);
            if (isCoronation){
                List<Integer> moveRange = defMoveRange(new int[][]{{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}, 1);
                range.addAll(moveRange);
            }
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},{-1,-1},{1,-1},{-1,1},{1,1}}, 1);
            if (isCoronation){
                List<Integer> eatRange = defEatRange(new int[][]{{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}, 1);
                range.addAll(eatRange);
            }
            return range;
        }

    }

    /**
     * 后
     */
    private static class Queen extends Chess {
        public Queen(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},{-1,-1},{1,-1},{-1,1},{1,1}}, Integer.MAX_VALUE);
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1},{-1,-1},{1,-1},{-1,1},{1,1}}, Integer.MAX_VALUE);
            return range;
        }

    }

    /**
     * 象
     */
    private static class Bishop extends Chess {
        public Bishop(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name,mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, Integer.MAX_VALUE);
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1, 1}, {-1, 1}, {-1, -1}, {1, -1}}, Integer.MAX_VALUE);
            return range;
        }

    }

    /**
     * 马
     */
    private static class Knight extends Chess {
        public Knight(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room, name,mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}, 1);
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            List<Integer> range = defEatRange(new int[][]{{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}}, 1);
            return range;
        }
    }

    /**
     * 车
     */
    private static class Rook extends Chess {
        public Rook(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}}, Integer.MAX_VALUE);
        }

    }

    /**
     * 兵
     */
    private static class Pawn extends Chess {
        public Pawn(JumpStepForeignChessRoom room, String name, int mSide, int pRow, int pCol) {
            super(room,name, mSide, pRow, pCol);
        }

        @Override
        public List<Integer> getMoveRange() {
            List<Integer> range = defMoveRange(new int[][]{{getFrontDirection(), 0}}, 1);
            return range;
        }

        @Override
        public List<Integer> getEatRange() {
            return defEatRange(new int[][]{{getFrontDirection(), -1}, {getFrontDirection(), 1}}, 1);
        }

        @Override
        public List<Integer> getPutRange(){
            Set<Integer> range = new HashSet<>();
            for (Chess chess : room.chessList) {
                if (chess.side != this.side && (chess instanceof King || chess instanceof Pawn)){ //兵只能打入兵和王前面
                    range.addAll(chess.getFrontAroundRange());
                }
            }
            return new ArrayList<>(range);
        }

        /**
         * 兵升变检查
         */
        public Chess evolution() {
            if (inEnemyBottomLine()){
                return new Queen(room, "后", side, row, col);
            }
            else {
                return this;
            }
        }
    }
}
